/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package control;

import java.util.ArrayList;
import java.util.Collections;

/**
 * Clase que contiene la logica de las operaciones de Regresion/Interpolación y
 * Metodos estadisticos de Dispersión y de Tendencia
 *
 * @author Zergio
 */
public class ComponenteMatematico {

    //(8) Interpolacion Lagrange
    public boolean MetodoInterpolacion(ArrayList<Double> tiempos, ArrayList<Double> imagenes, int numeroPredicciones) {

        /**
         * Tiempos hace referencia a los momentos t medidos Imagenes hace
         * referencia a los valores de esas mediciones
         *
         * Se hace una interpolación de valores para minimo dos puntos de data y
         * maximo 4(las ultimas 4)
         *
         * retorna falso si ahi pocos datos (util para mostrar errores)
         */
        boolean flag = true;
        int n;
        double x, y;
        double a[][] = new double[4][2];

        System.out.println(imagenes.size() + "\n");

        if (tiempos.size() < 2) {
            flag = false;
        }
        if (tiempos.size() > 4) {
            do {
                System.out.println("1");
                tiempos.remove(1);
                imagenes.remove(1);
            } while (tiempos.size() > 4);

        }


        n = tiempos.size();
        System.out.println(n + "\n");

        for (int j = 1; j <= n; j++) {

            a[j - 1][0] = tiempos.get(j - 1);

            a[j - 1][1] = imagenes.get(j - 1);
        }

        double valorTope = tiempos.get(tiempos.size() - 1);

        for (int i = 1; i <= numeroPredicciones; i++) {
            x = valorTope + i;

            switch (n) {
                case 2:
                    y = (((((x - a[1][0]) * a[0][1]) / (a[0][0] - a[1][0])) + (((x - a[0][0]) * a[1][1]) / (a[1][0] - a[0][0]))));
                    tiempos.add(x);
                    imagenes.add(y);


                    break;
                case 3:
                    y = ((x - a[1][0]) * (x - a[2][0]) * a[0][1]) / ((a[0][0] - a[1][0]) * (a[0][0] - a[2][0])) + ((x - a[0][0]) * (x - a[2][0]) * a[1][1]) / ((a[1][0] - a[0][0]) * (a[1][0] - a[2][0])) + ((x - a[1][0]) * ((x - a[0][0]) * a[2][1]) / ((a[2][0] - a[0][0]) * (a[2][0] - a[1][0])));
                    tiempos.add(x);
                    imagenes.add(y);
                    break;
                case 4:
                    y = ((x - a[1][0]) * (x - a[3][0]) * (x - a[2][0]) * a[0][1]) / ((a[0][0] - a[1][0]) * (a[0][0] - a[2][0]) * (a[0][0] - a[3][0])) + ((x - a[0][0]) * (x - a[2][0]) * (x - a[3][0]) * a[1][1]) / ((a[1][0] - a[0][0]) * (a[1][0] - a[2][0]) * (a[1][0] - a[3][0])) + ((x - a[0][0]) * (x - a[1][0]) * ((x - a[3][0]) * a[2][1]) / ((a[2][0] - a[0][0]) * (a[2][0] - a[1][0]) * (a[2][0] - a[3][0])) + ((x - a[0][0]) * (x - a[1][0]) * ((x - a[2][0]) * a[
3][1]) / ((a[3][0] - a[0][0]) * (a[3][0] - a[1][0]) * (a[3][0] - a[2][0]))));
                    tiempos.add(x);
                    imagenes.add(y);
                    break;
                default:
                    flag = false;
                    break;

//TODO Cambiar impresiones de Linea por Appends a Listas Ingresadas
            }
        }
        return flag;
    }

    public double CalculaMediana(ArrayList<Double> datos) {

        Collections.sort(datos);

        int medio = datos.size() / 2;

        if (datos.size() % 2 == 1) {
            return datos.get(medio);
        } else {
            return (datos.get(medio) + datos.get(medio - 1)) / 2;
        }


    }

    public double CalculaModa(ArrayList<Double> datos) {
        int cuentaMaxima = 0;
        double valorMaximo = 0;

        for (int i = 0; i < datos.size(); ++i) {
            int temp = 0;
            for (int j = 0; j < datos.size(); ++j) {
                if (datos.get(j) == datos.get(i)) {
                    ++temp;
                }
            }
            if (temp > cuentaMaxima) {
                cuentaMaxima = temp;
                valorMaximo = datos.get(i);
            }
        }

        return valorMaximo;
    }

    public double CalculaMedia(ArrayList<Double> datos) {
        double sum = 0;
        for (int i = 0; i < datos.size(); i++) {
            sum += datos.get(i);
        }
        return sum / datos.size();
    }

    public double CalculaDesviacion(ArrayList<Double> datos) {
        return Math.sqrt(CalculaVarianza(datos));
    }

    public double CalculaRango(ArrayList<Double> datos) {
        return 0;
    }

    public double CalculaVarianza(ArrayList<Double> datos) {
        double promedio = CalculaMedia(datos);
        double sum = 0;
        for (int i = 1; i <= datos.size(); i++) {
            sum += Math.pow((datos.get(i) - promedio), 2);
        }
        return sum / (datos.size() - 1);
    }
}
